/**
 * @FilePath: \ros2\src\tools\shared_parameters\src\include\shared_parameters\log.hpp
 * @Description  :  
 * @Author       : haibo
 * @Version      : 1.0.0
 * @LastEditors: haibo ashengzi@163.com
 * @LastEditTime: 2025-02-20 20:37:31
 * @Copyright (c) 2025 by 临工智能信息科技有限公司, All Rights Reserved. 
**/

#pragma once
#include <filesystem>
#include <fstream>
#include <string>
#include <cstdlib>
#include <mutex>
#include <chrono>
#include <ctime>
#include <cstdarg>
#include <memory>

constexpr int FILESIZE = 10; // MB
namespace fs = std::filesystem;

class Logger {
public:
    static Logger& instance() {
        static Logger instance;
        return instance;
    }
    
    Logger(const Logger&) = delete;
    Logger& operator=(const Logger&) = delete;

    void log(const char* format, ...) {
        std::lock_guard<std::mutex> lock(mutex_);
        
        va_list args;
        va_start(args, format);
        write_log(format, args);
        va_end(args);
    }

private:
    Logger() {
        init_log_path();
        ensure_directory();
    }

    void init_log_path() {
        if (const char* ros_log = std::getenv("ROS_LOG_DIR")) {
            log_path_ = fs::path(ros_log) / "shared_parameters.log";
            return;
        }

        const char* home = std::getenv("HOME");
        if (!home) throw std::runtime_error("Missing HOME environment variable");
        log_path_ = fs::path(home) / "log" / "shared_parameters.log";

        log("Log path initialized to: %s", log_path_.c_str());
    }

    void ensure_directory() const {
        fs::create_directories(log_path_.parent_path());
    }

    void rotate_if_needed() {
        if (fs::exists(log_path_) && fs::file_size(log_path_) >= FILESIZE * 1024 * 1024) {
            std::ofstream(log_path_, std::ios::trunc).close();
        }
    }

    void write_log(const char* format, va_list args) {
        rotate_if_needed();

        char buffer[4096];
        vsnprintf(buffer, sizeof(buffer), format, args);

        std::ofstream ofs(log_path_, std::ios::app);
        if (ofs) {
            auto now = std::chrono::system_clock::now();
            auto t = std::chrono::system_clock::to_time_t(now);
            ofs << "[" << std::put_time(std::localtime(&t), "%F %T") << "] [DEBUG] " 
                << buffer << "\n";
        }
    }

    fs::path log_path_;
    std::mutex mutex_;
};

#define DEBUG(...) Logger::instance().log(__VA_ARGS__)
